(function (angular) {
    'use strict';
    angular.module('fs.common').factory("commonService", ['$filter', '$q', 'HttpConstants', 'ajaxServiceFactory', 'dateService', 'modalService',
        function ($filter, $q, HttpConstants, ajaxServiceFactory, dateService, modalService) {
            return {
                hash: buildObjectHashCode,
                isHoliday: isHoliday,
                getHolidays: getHolidays,
                download: download,
                openDocument: openDocument
            };
            //params like {calendarYear : '2017', calendarCodes : ['U:FSCSBK:XXX', 'O:FSCSBK']}
            function getHolidays(params, url) {
                var defer = $q.defer();
                var ajaxService = ajaxServiceFactory.buildAjaxService({
                    getHolidays: {
                        url: url || HttpConstants.GET_HOLIDAYD_URL,
                        method: 'post'
                    }
                });
                ajaxService.getHolidays(params).then(function (response) {
                    defer.resolve(response ? response.data : []);
                }, function (e) {
                    defer.reject(e);
                });
                return defer.promise;
            }
            function buildDownloadService(params, url) {
                if ('N' != params.isTemporary) {
                    url = url || HttpConstants.DOWNLOAD_TEMPDOC_URL;
                } else {
                    url = url || HttpConstants.DOWNLOAD_DOC_URL;
                }
                var ajaxService = ajaxServiceFactory.buildAjaxService({
                    download: {
                        method: 'POST',
                        url: url,
                        responseType: 'arraybuffer',
                        cache: false,
                        transformResponse: function (data, headers) {
                            var blob = null;
                            var contentType = headers('content-type');
                            var fileName;
                            if (params.fileName) {
                                fileName = params.fileName;
                            } else {
                                fileName = headers('content-disposition');
                            }
                            if (fileName) {
                                fileName = fileName.split(";")[1].trim().split("=")[1];
                                fileName = fileName.replace(/"/g, '');
                            }
                            if (data) {
                                blob = new Blob([data], {
                                    type: contentType
                                });
                            }
                            var result = {
                                blob: blob,
                                fileName: fileName
                            };
                            return {
                                data: result
                            };
                        }
                    }
                });
                return ajaxService;
            }
            function download(params, url) {
                var downloadService, defer = $q.defer();
                try {
                    downloadService = buildDownloadService(params, url);
                    downloadService.download(params).then(function (response, headers) {
                        if (response && response.data) {
                            saveAs(response.data.blob, response.data.fileName);
                            defer.resolve(response);
                        } else {
                            defer.reject();
                        }
                    });
                } catch (e) {
                    defer.reject(e);
                }
                return defer.promise;
            }
            function open(params, blob, fileName) {
                if (blob) {
                    if (blob.type.indexOf('image/') != -1) {
                        openImage(params, blob);
                    } else if (blob.type.indexOf('text/') != -1) {
                        openText(params, blob);
                    } else if (blob.type == 'application/pdf') {
                        openPdf(params, blob);
                    } else {
                        saveAs(blob, fileName);
                    }
                }
            }
            function openText(params, blob) {
                var url = $filter('trustedResourceUrl')(URL.createObjectURL(blob));
                params.type = blob.type;
                _openDoc('waf.text.viewer', url, params);

            }
            function openPdf(params, blob) {
                var url = URL.createObjectURL(blob);
                params.type = blob.type;
                _openDoc('waf.pdf.viewer', url, params);
            }
            function openImage(params, blob) {
                var url = $filter('trustedResourceUrl')(URL.createObjectURL(blob));
                params.type = blob.type;
                _openDoc('waf.image.viewer', url, params);
            }
            function _openDoc(dialogsModuleId, url, params) {
                modalService.openCustomDialogs({
                    'dialogsModule': dialogsModuleId,
                    'size': params.size || [652, 580],
                    'params': {
                        'url': url,
                        'type': params.type
                    }
                });
            }
            function openDocument(params, url, newWindow, filterParams) {
                var downloadService, defer = $q.defer();
                try {
                    if (newWindow) {
                        openDocumentInNewWindow(params, url, filterParams);
                        defer.resolve();
                        return defer.promise;
                    }
                    downloadService = buildDownloadService(params, url);
                    downloadService.download(params).then(function (response, headers) {
                        if (response && response.data) {
                            open(params, response.data.blob, response.data.fileName);
                            defer.resolve(response);
                        } else {
                            defer.reject();
                        }
                    }, function (e) {
                        defer.reject(e);
                    });
                } catch (e) {
                    defer.reject(e);
                }
                return defer.promise;
            }
            function openDocumentInNewWindow(params, url, filterParmas) {
                var $form = angular.element('<form action=' + url + ' method="post" target="_blank" style="display:none"></form>');
                var csrfToken = HttpConstants.CSRF_TOKEN ? storageService.getItemFromSession(HttpConstants.CSRF_TOKEN) : undefined;
                var transToken = HttpConstants.TRANSACTION_TOKEN ? storageService.getItemFromSession(HttpConstants.TRANSACTION_TOKEN) : undefined;
                params = angular.copy(params);
                if (filterParmas) {
                    angular.forEach(filterParmas, function (p) {
                        $parse(p).assign(params, null);
                    });
                }
                if (csrfToken) {
                    params[HttpConstants.CSRF_TOKEN] = csrfToken;
                }
                if (transToken) {
                    params[HttpConstants.TRANSACTION_TOKEN] = transToken;
                }
                params = toFlat(params);
                params = formatRequestDate(params);
                angular.forEach(params, function (value, key) {
                    var input;
                    if (angular.isArray(value)) {
                        angular.forEach(value, function (v) {
                            input = angular.element('<input type="hidden" name="' + key + '"/>');
                            input[0].value = v;
                            $form.append(input);
                        });
                    } else if (value != null && value != undefined) {
                        input = angular.element('<input type="hidden" name="' + key + '"/>');
                        input[0].value = value;
                        $form.append(input);
                    }
                });
                angular.element($document[0].querySelector('body')).append($form);
                $document[0].forms[$document[0].forms.length - 1].submit();
                $form.remove();
            }
            function toFlat(map) {
                var flatValue = {};
                if (angular.isArray(map)) {
                    return flatValue;
                } else if (angular.isObject(map)) {
                    Object.keys(map).filter(function (key) {
                        var value = map[key];
                        if (angular.isArray(value)) {
                            angular.forEach(value, function (v, k) {
                                if (angular.isObject(v) && !angular.isDate(v)) {
                                    v = toFlat(v);
                                    Object.keys(v).filter(function (k2) {
                                        flatValue[key + '[' + k + '].' + k2] = v[k2];
                                    });
                                } else {
                                    flatValue[key + '[' + k + ']'] = v;
                                }
                            });
                        } else if (angular.isObject(value) && !angular.isDate(value)) {
                            value = toFlat(value);
                            Object.keys(value).filter(function (key2) {
                                flatValue[key + '.' + key2] = value[key2];
                            });
                        } else {
                            flatValue[key] = value;
                        }
                    });
                }
                return flatValue;
            }
            function formatRequestDate(requestData) {
                var formatter = storageService.getFormatInfo().longTimestamp;
                function formatDate(requestData) {
                    angular.forEach(requestData, function (value, key) {
                        if (!requestData.hasOwnProperty(key)) return;
                        if (angular.isDate(value)) {
                            requestData[key] = $filter('date')(value, formatter);
                        } else if (angular.isObject(value)) {
                            formatDate(value);
                        }
                    });
                }
                formatDate(requestData);
                return requestData;
            }
            function buildObjectHashCode(object) {
                var str;
                if (!angular.isObject(object)) {
                    return hash('');
                }
                str = toString(object);
                return hash(str || '');

            }
            function toString(object) {
                var t = [], str;
                if (angular.isArray(object)) {
                    angular.forEach(object, function (o) {
                        str = toString(o);
                        if (str) {
                            t.push(str);
                        }
                    });
                } else if (angular.isDate(object) || angular.isNumber(object)) {
                    t.push(object.toString());
                } else {
                    angular.forEach(object, function (v, k) {
                        if (angular.isString(k) && k.indexOf('$') < 0 && k.indexOf('_') < 0 && !(v === null || angular.isUndefined(v) || (angular.isString(v) ? v.trim() == '' : false))) {
                            if (angular.isArray(v)) {
                                angular.forEach(v, function (o) {
                                    if (angular.isArray(o)) {
                                        str = toString(o);
                                        if (str) {
                                            t.push(str);
                                        }
                                    } else if (angular.isObject(o)) {
                                        str = toString(o);
                                        if (str) {
                                            t.push(str);
                                        }
                                    } else {
                                        str = toString(o);
                                        if (str) {
                                            t.push(str);
                                        }
                                    }
                                });
                            } else if (angular.isObject(v)) {
                                str = toString(v);
                                if (str) {
                                    t.push(str);
                                }
                            } else if (angular.isNumber(v)) {
                                t.push(v.toString());
                            } else {
                                t.push(v);
                            }
                        }
                    });
                }
                return t.length > 0 ? t.join(',') : undefined;
            }
            function hash(str) {
                var h = 0, i = 0, n;
                var strlen = str.length;
                if (strlen === 0) {
                    return h;
                }
                for (i = 0, n; i < strlen; ++i) {
                    n = str.charCodeAt(i);
                    h = ((h << 5) - h) + n;
                    h = h & h;
                }
                return h >>> 0;
            }
        }]);
})(angular);